feat: enable sharing of chat sessions#1935
Open
onematchfox wants to merge 1 commit into
Open
Conversation
Closes kagent-dev#1933 Signed-off-by: Brian Fox <878612+onematchfox@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds end-to-end “shared session” support via share tokens, including UI affordances to create/manage share links, frontend propagation of X-Share-Token, and backend persistence + enforcement (read-only vs read-write) for shared access.
Changes:
- UI: create/manage share links, show shared-session indicators, and propagate share tokens through chat/task/A2A calls.
- Backend (Go): add session share tables, middleware validation/enforcement, share CRUD endpoints, and session listing enhancements with share metadata.
- Agent runtimes (Python/Go ADK) + Helm/CRDs: optional “share tools” injection and
KAGENT_UI_URLplumbing for generating clickable share URLs.
Reviewed changes
Copilot reviewed 54 out of 59 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| ui/src/types/index.ts | Extends Session type with optional share_token and share_read_only. |
| ui/src/lib/auth.ts | Forwards x-share-token header by default. |
| ui/src/lib/a2aClient.ts | Allows attaching X-Share-Token to streaming A2A requests; tightens types. |
| ui/src/lib/tests/auth.test.ts | Updates default-forward-header expectations for share token forwarding. |
| ui/src/components/sidebars/SessionGroup.tsx | Passes share metadata down to chat items. |
| ui/src/components/sidebars/ChatItem.tsx | Appends ?share=... to shared-session links and shows shared icon. |
| ui/src/components/chat/ShareButton.tsx | New client component to create/copy/revoke share links. |
| ui/src/components/chat/ChatMessage.tsx | Simplifies ask-user submit callback wiring. |
| ui/src/components/chat/ChatInterface.tsx | Propagates share token through reads/A2A and enforces read-only UI mode; adds ShareButton. |
| ui/src/components/chat/AskUserDisplay.tsx | Disables ask-user interactions when handlers are absent (read-only mode). |
| ui/src/components/ToolDisplay.tsx | Disables approve/reject buttons when no handlers (read-only mode). |
| ui/src/app/agents/[namespace]/[name]/chat/[chatId]/page.tsx | Reads share query param and passes it to ChatInterface (with Suspense). |
| ui/src/app/actions/sessions.ts | Adds optional shareToken header support for session/task fetches + getSessionWithEvents. |
| ui/src/app/actions/sessionShares.ts | New server actions for session share CRUD. |
| python/packages/kagent-adk/tests/unittests/test_share_tools.py | Adds unit tests for Python share tools. |
| python/packages/kagent-adk/src/kagent/adk/types.py | Adds share_tools flag to AgentConfig and injects share tools when enabled. |
| python/packages/kagent-adk/src/kagent/adk/tools/share_tools.py | Implements Python ADK share tools and URL generation. |
| python/packages/kagent-adk/src/kagent/adk/tools/init.py | Exports the new Python share tools. |
| helm/kagent/values.yaml | Adds controller.externalUrl for setting KAGENT_UI_URL. |
| helm/kagent/templates/controller-deployment.yaml | Injects KAGENT_UI_URL into controller when configured. |
| helm/kagent-crds/templates/kagent.dev_sandboxagents.yaml | Adds shareTools field to rendered CRD schema. |
| helm/kagent-crds/templates/kagent.dev_agents.yaml | Adds shareTools field to rendered CRD schema. |
| go/core/pkg/migrations/core/000005_session_shares.up.sql | Adds session_share and session_share_access tables. |
| go/core/pkg/migrations/core/000005_session_shares.down.sql | Adds down migration (currently only drops one table). |
| go/core/pkg/env/kagent.go | Registers KAGENT_UI_URL env var. |
| go/core/pkg/auth/share_test.go | Unit tests for ShareContext helpers. |
| go/core/pkg/auth/share.go | Adds ShareContext storage/retrieval in request context. |
| go/core/internal/httpserver/server_share_middleware_test.go | Adds tests for share-token middleware behavior. |
| go/core/internal/httpserver/server.go | Registers share routes and share-token middleware. |
| go/core/internal/httpserver/middleware.go | Implements share-token validation, read-only enforcement, and access recording. |
| go/core/internal/httpserver/handlers/sessions_test.go | Extends session handler tests for read_only field + updated list type. |
| go/core/internal/httpserver/handlers/sessions_share_context_test.go | Adds tests for effective user ID resolution under share context. |
| go/core/internal/httpserver/handlers/sessions.go | Uses ShareContext for DB lookups + returns read_only in responses. |
| go/core/internal/httpserver/handlers/session_shares_test.go | Adds tests for session share CRUD handlers. |
| go/core/internal/httpserver/handlers/session_shares.go | Implements session share CRUD endpoints. |
| go/core/internal/httpserver/handlers/handlers.go | Wires SessionSharesHandler into handler set. |
| go/core/internal/httpserver/auth/authn.go | Forces agent upstream calls to use share owner’s X-User-Id when share context present. |
| go/core/internal/database/queries/sessions.sql | Enhances session listing to include shared sessions and share metadata. |
| go/core/internal/database/queries/session_shares.sql | Adds SQL queries for share CRUD and access upsert. |
| go/core/internal/database/client_postgres.go | Implements DB methods for shares + new session list return type. |
| go/core/internal/controller/translator/agent/manifest_builder.go | Propagates KAGENT_UI_URL into agent pods when set. |
| go/core/internal/controller/translator/agent/compiler.go | Passes shareTools flag into ADK AgentConfig. |
| go/core/internal/a2a/manager_test.go | Tests initiated_by injection when share context is present. |
| go/core/internal/a2a/manager.go | Injects initiated_by metadata for shared-session A2A messages. |
| go/api/v1alpha2/agent_types.go | Adds shareTools field to Agent CRD Go types. |
| go/api/database/models.go | Adds SessionWithShareToken and SessionShare models. |
| go/api/database/client.go | Extends DB client interface with share methods and updated session list signature. |
| go/api/config/crd/bases/kagent.dev_sandboxagents.yaml | Adds shareTools to generated CRD base. |
| go/api/config/crd/bases/kagent.dev_agents.yaml | Adds shareTools to generated CRD base. |
| go/api/adk/types.go | Adds share_tools to ADK AgentConfig JSON handling. |
| go/adk/pkg/tools/share_tools_test.go | Adds tests for Go ADK share tools. |
| go/adk/pkg/tools/share_tools.go | Implements Go ADK share tools and URL generation. |
| go/adk/pkg/runner/adapter.go | Conditionally injects share tools into Go ADK runner. |
| go/adk/cmd/main.go | Passes HTTP client + kagent URL into runner config for share tools. |
Files not reviewed (5)
- go/api/v1alpha2/zz_generated.deepcopy.go: Language not supported
- go/core/internal/database/gen/models.go: Language not supported
- go/core/internal/database/gen/querier.go: Language not supported
- go/core/internal/database/gen/session_shares.sql.go: Language not supported
- go/core/internal/database/gen/sessions.sql.go: Language not supported
Comments suppressed due to low confidence (8)
go/core/pkg/migrations/core/000005_session_shares.down.sql:1
- The down migration drops
session_sharebut notsession_share_access. Sincesession_share_accesshas a foreign key referencingsession_share, droppingsession_sharefirst will fail in Postgres (or leave orphaned objects depending on settings). Dropsession_share_accessfirst, thensession_share(and consider dropping the index too for completeness).
ui/src/components/chat/ShareButton.tsx:1 - This references
windowduring render. In Next.js App Router, client components can still be pre-rendered on the server, wherewindowis undefined, causing a runtime crash. Computeorigininside an effect (store in state), or guard withtypeof window !== \"undefined\"before readingwindow.location.origin.
ui/src/components/chat/ChatInterface.tsx:1 shareReadOnlyis only set inside theshareTokenbranch. If the user navigates from a shared read-only session to a non-shared session without a full remount,shareReadOnlycan remaintrueand incorrectly disable interactions. ResetshareReadOnlytofalsewhenshareTokenis absent (e.g., at the start of initialization or in theelsebranch).
ui/src/components/chat/ChatInterface.tsx:1shareReadOnlyis only set inside theshareTokenbranch. If the user navigates from a shared read-only session to a non-shared session without a full remount,shareReadOnlycan remaintrueand incorrectly disable interactions. ResetshareReadOnlytofalsewhenshareTokenis absent (e.g., at the start of initialization or in theelsebranch).
ui/src/components/chat/ChatInterface.tsx:1shareReadOnlyis only set inside theshareTokenbranch. If the user navigates from a shared read-only session to a non-shared session without a full remount,shareReadOnlycan remaintrueand incorrectly disable interactions. ResetshareReadOnlytofalsewhenshareTokenis absent (e.g., at the start of initialization or in theelsebranch).
ui/src/components/sidebars/ChatItem.tsx:1- The share token is inserted into the URL query string without encoding and will be stored in browser history and may leak via referrer headers/logs. At minimum, wrap the token with
encodeURIComponent(or build viaURLSearchParams) to prevent malformed URLs; consider using a URL fragment (e.g.#share=...) if feasible so the token is not emitted as an HTTP referrer, while still being readable by the client.
python/packages/kagent-adk/src/kagent/adk/tools/share_tools.py:1 - Docstring says that without
KAGENT_UI_URLthe function returns only the raw token, but the implementation returns a relative path containing?share=<token>. Update the docstring to match actual behavior (relative path vs raw token).
ui/src/components/chat/ShareButton.tsx:1 - This input has no accessible name (no associated
<Label>and noaria-label), which makes the share URL harder to discover for screen reader users. Add anaria-label(e.g. "Share link") or associate it with a visible label.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+147
to
+156
| userID, err := GetUserID(r) | ||
| if err != nil { | ||
| w.RespondWithError(errors.NewBadRequestError("failed to get user ID", err)) | ||
| return | ||
| } | ||
|
|
||
| if err := h.DatabaseService.DeleteSessionShare(r.Context(), token, sessionID, userID); err != nil { | ||
| w.RespondWithError(errors.NewInternalServerError("failed to delete share", err)) | ||
| return | ||
| } |
Comment on lines
+14
to
+25
| ELSE (SELECT ss.token FROM session_share ss | ||
| JOIN session_share_access sa ON sa.share_id = ss.id | ||
| WHERE ss.session_id = s.id AND sa.user_id = $2 | ||
| ORDER BY ss.read_only ASC, ss.created_at DESC LIMIT 1) | ||
| END) AS share_token, | ||
| (CASE WHEN s.user_id = $2 THEN NULL::boolean | ||
| ELSE (SELECT ss.read_only FROM session_share ss | ||
| JOIN session_share_access sa ON sa.share_id = ss.id | ||
| WHERE ss.session_id = s.id AND sa.user_id = $2 | ||
| ORDER BY ss.read_only ASC, ss.created_at DESC LIMIT 1) | ||
| END) AS share_read_only | ||
| FROM session s |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Design choices are documented in #1933. Will address/respond to comments either here or there if needed and keep the implementation in sync as we go.
Closes #1933